# -*- coding: utf-8 -*-
"""
B站API接口模块
提供B站视频信息获取、解析等功能
"""

import re
import json
import time
import requests
from typing import Dict, List, Optional, Tuple
from urllib.parse import urlparse, parse_qs

from .utils import (
    validate_bilibili_url, 
    extract_video_id, 
    setup_logger,
    parse_quality_description
)


class BilibiliAPI:
    """
    B站API接口类
    提供视频信息获取、解析等功能
    """
    
    def __init__(self):
        self.session = requests.Session()
        self.logger = setup_logger('BilibiliAPI')
        
        # 设置请求头，模拟浏览器访问
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Referer': 'https://www.bilibili.com/',
            'Accept': 'application/json, text/plain, */*',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
        })
        
        # API端点
        self.api_base = 'https://api.bilibili.com'
        self.video_info_api = f'{self.api_base}/x/web-interface/view'
        self.video_stream_api = f'{self.api_base}/x/player/playurl'
        
        # 重试配置
        self.max_retries = 3
        self.retry_delay = 1
    
    def _make_request(self, url: str, params: Optional[Dict] = None, timeout: int = 10) -> Optional[Dict]:
        """
        发送HTTP请求并处理重试
        
        Args:
            url: 请求URL
            params: 请求参数
            timeout: 超时时间
            
        Returns:
            dict: 响应JSON数据，失败返回None
        """
        for attempt in range(self.max_retries):
            try:
                response = self.session.get(url, params=params, timeout=timeout)
                response.raise_for_status()
                
                data = response.json()
                if data.get('code') == 0:
                    return data
                else:
                    self.logger.warning(f"API返回错误: {data.get('message', '未知错误')}")
                    return None
                    
            except requests.exceptions.RequestException as e:
                self.logger.warning(f"请求失败 (尝试 {attempt + 1}/{self.max_retries}): {e}")
                if attempt < self.max_retries - 1:
                    time.sleep(self.retry_delay * (attempt + 1))
                    
            except json.JSONDecodeError as e:
                self.logger.error(f"JSON解析失败: {e}")
                return None
        
        self.logger.error(f"请求最终失败: {url}")
        return None
    
    def parse_video_url(self, url: str) -> Optional[Dict[str, str]]:
        """
        解析视频URL，提取视频ID和相关信息
        
        Args:
            url: B站视频URL
            
        Returns:
            dict: 包含视频ID、类型等信息的字典
        """
        if not validate_bilibili_url(url):
            self.logger.error(f"无效的B站URL: {url}")
            return None
        
        video_id = extract_video_id(url)
        if not video_id:
            self.logger.error(f"无法提取视频ID: {url}")
            return None
        
        # 解析URL获取额外参数
        parsed_url = urlparse(url)
        query_params = parse_qs(parsed_url.query)
        
        result = {
            'video_id': video_id,
            'original_url': url,
            'type': 'bv' if video_id.startswith(('BV', 'bv')) else 'av'
        }
        
        # 提取分P信息
        if 'p' in query_params:
            try:
                result['page'] = int(query_params['p'][0])
            except (ValueError, IndexError):
                result['page'] = 1
        else:
            result['page'] = 1
        
        # 提取时间戳信息
        if 't' in query_params:
            try:
                result['start_time'] = int(query_params['t'][0])
            except (ValueError, IndexError):
                result['start_time'] = 0
        
        self.logger.info(f"成功解析视频URL: {video_id}")
        return result
    
    def get_video_info(self, video_id: str) -> Optional[Dict]:
        """
        获取视频基本信息
        
        Args:
            video_id: 视频ID（BV号或av号）
            
        Returns:
            dict: 视频信息字典
        """
        # 构建请求参数
        if video_id.startswith(('BV', 'bv')):
            params = {'bvid': video_id}
        elif video_id.startswith('av'):
            params = {'aid': video_id[2:]}  # 移除'av'前缀
        else:
            self.logger.error(f"无效的视频ID格式: {video_id}")
            return None
        
        # 发送请求
        data = self._make_request(self.video_info_api, params)
        if not data:
            return None
        
        try:
            video_data = data['data']
            
            # 提取视频信息
            info = {
                'bvid': video_data.get('bvid', ''),
                'aid': video_data.get('aid', 0),
                'title': video_data.get('title', ''),
                'description': video_data.get('desc', ''),
                'duration': video_data.get('duration', 0),
                'view_count': video_data.get('stat', {}).get('view', 0),
                'like_count': video_data.get('stat', {}).get('like', 0),
                'coin_count': video_data.get('stat', {}).get('coin', 0),
                'favorite_count': video_data.get('stat', {}).get('favorite', 0),
                'share_count': video_data.get('stat', {}).get('share', 0),
                'danmaku_count': video_data.get('stat', {}).get('danmaku', 0),
                'reply_count': video_data.get('stat', {}).get('reply', 0),
                'upload_time': video_data.get('pubdate', 0),
                'thumbnail': video_data.get('pic', ''),
                'owner': {
                    'uid': video_data.get('owner', {}).get('mid', 0),
                    'name': video_data.get('owner', {}).get('name', ''),
                    'avatar': video_data.get('owner', {}).get('face', '')
                },
                'pages': []
            }
            
            # 提取分P信息
            pages = video_data.get('pages', [])
            for page in pages:
                page_info = {
                    'page': page.get('page', 1),
                    'part': page.get('part', ''),
                    'duration': page.get('duration', 0),
                    'cid': page.get('cid', 0)
                }
                info['pages'].append(page_info)
            
            self.logger.info(f"成功获取视频信息: {info['title']}")
            return info
            
        except KeyError as e:
            self.logger.error(f"解析视频信息失败: {e}")
            return None
    
    def get_video_stream_info(self, video_id: str, cid: int, quality: int = 80) -> Optional[Dict]:
        """
        获取视频流信息
        
        Args:
            video_id: 视频ID
            cid: 视频分P的cid
            quality: 视频质量ID (80=1080P, 64=720P, 32=480P, 16=360P)
            
        Returns:
            dict: 视频流信息
        """
        # 构建请求参数
        if video_id.startswith(('BV', 'bv')):
            params = {
                'bvid': video_id,
                'cid': cid,
                'qn': quality,
                'fnval': 16,  # 获取dash格式
                'fourk': 1    # 支持4K
            }
        elif video_id.startswith('av'):
            params = {
                'avid': video_id[2:],
                'cid': cid,
                'qn': quality,
                'fnval': 16,
                'fourk': 1
            }
        else:
            self.logger.error(f"无效的视频ID格式: {video_id}")
            return None
        
        # 发送请求
        data = self._make_request(self.video_stream_api, params)
        if not data:
            return None
        
        try:
            stream_data = data['data']
            
            result = {
                'quality': stream_data.get('quality', 0),
                'format': stream_data.get('format', ''),
                'timelength': stream_data.get('timelength', 0),
                'accept_quality': stream_data.get('accept_quality', []),
                'accept_description': stream_data.get('accept_description', []),
                'video_streams': [],
                'audio_streams': []
            }
            
            # 解析DASH格式流信息
            if 'dash' in stream_data:
                dash_data = stream_data['dash']
                
                # 视频流
                for video in dash_data.get('video', []):
                    video_info = {
                        'id': video.get('id', 0),
                        'base_url': video.get('base_url', ''),
                        'backup_url': video.get('backup_url', []),
                        'bandwidth': video.get('bandwidth', 0),
                        'mime_type': video.get('mime_type', ''),
                        'codecs': video.get('codecs', ''),
                        'width': video.get('width', 0),
                        'height': video.get('height', 0),
                        'frame_rate': video.get('frame_rate', ''),
                        'sar': video.get('sar', ''),
                        'start_with_sap': video.get('start_with_sap', 0),
                        'segment_base': video.get('segment_base', {})
                    }
                    result['video_streams'].append(video_info)
                
                # 音频流
                for audio in dash_data.get('audio', []):
                    audio_info = {
                        'id': audio.get('id', 0),
                        'base_url': audio.get('base_url', ''),
                        'backup_url': audio.get('backup_url', []),
                        'bandwidth': audio.get('bandwidth', 0),
                        'mime_type': audio.get('mime_type', ''),
                        'codecs': audio.get('codecs', ''),
                        'segment_base': audio.get('segment_base', {})
                    }
                    result['audio_streams'].append(audio_info)
            
            # 解析传统格式流信息（备用）
            elif 'durl' in stream_data:
                for durl in stream_data['durl']:
                    video_info = {
                        'url': durl.get('url', ''),
                        'backup_url': durl.get('backup_url', []),
                        'length': durl.get('length', 0),
                        'size': durl.get('size', 0)
                    }
                    result['video_streams'].append(video_info)
            
            self.logger.info(f"成功获取视频流信息: 质量={quality}")
            return result
            
        except KeyError as e:
            self.logger.error(f"解析视频流信息失败: {e}")
            return None
    
    def get_available_qualities(self, video_id: str, cid: int) -> List[Dict[str, any]]:
        """
        获取视频可用的质量选项
        
        Args:
            video_id: 视频ID
            cid: 视频分P的cid
            
        Returns:
            list: 可用质量列表
        """
        stream_info = self.get_video_stream_info(video_id, cid)
        if not stream_info:
            return []
        
        qualities = []
        accept_quality = stream_info.get('accept_quality', [])
        accept_description = stream_info.get('accept_description', [])
        
        for i, quality_id in enumerate(accept_quality):
            description = accept_description[i] if i < len(accept_description) else f"质量{quality_id}"
            
            quality_info = {
                'quality_id': quality_id,
                'description': description,
                'parsed_info': parse_quality_description(description)
            }
            qualities.append(quality_info)
        
        return qualities
    
    def search_videos(self, keyword: str, page: int = 1, page_size: int = 20) -> Optional[Dict]:
        """
        搜索视频
        
        Args:
            keyword: 搜索关键词
            page: 页码
            page_size: 每页数量
            
        Returns:
            dict: 搜索结果
        """
        search_api = f'{self.api_base}/x/web-interface/search/type'
        params = {
            'search_type': 'video',
            'keyword': keyword,
            'page': page,
            'page_size': page_size,
            'order': 'totalrank',  # 按综合排序
            'duration': 0,  # 不限时长
            'tids': 0  # 不限分区
        }
        
        data = self._make_request(search_api, params)
        if not data:
            return None
        
        try:
            search_data = data['data']
            result = {
                'page': search_data.get('page', 1),
                'page_size': search_data.get('pagesize', 20),
                'total': search_data.get('numResults', 0),
                'videos': []
            }
            
            for item in search_data.get('result', []):
                video_info = {
                    'bvid': item.get('bvid', ''),
                    'aid': item.get('aid', 0),
                    'title': item.get('title', ''),
                    'description': item.get('description', ''),
                    'duration': item.get('duration', ''),
                    'author': item.get('author', ''),
                    'view_count': item.get('play', 0),
                    'danmaku_count': item.get('video_review', 0),
                    'upload_time': item.get('pubdate', 0),
                    'thumbnail': item.get('pic', '')
                }
                result['videos'].append(video_info)
            
            self.logger.info(f"搜索完成: 关键词={keyword}, 结果数={len(result['videos'])}")
            return result
            
        except KeyError as e:
            self.logger.error(f"解析搜索结果失败: {e}")
            return None
    
    def close(self):
        """
        关闭会话
        """
        self.session.close()
        self.logger.info("API会话已关闭")